package com.only4play.common.utils;

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;

/**
 * Http响应工具类
 *
 * @author liyuncong
 * @date 2023/11/06 14:42
 **/
public class HttpResponseUtils {

    private static final String HEADER_CONTENT_TYPE = "Content-Type";
    private static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
    private static final String HEADER_ATTACHMENT = "attachment; filename=";
    private static final String HEADER_INLINE = "inline; filename=";

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        String mimeType,
        File file
    ) {
        final MediaType mediaType = MediaType.parseMediaType(mimeType);
        return sendAttachment(attachmentFilename, mediaType, file);
    }

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        String mimeType,
        ByteArrayOutputStream outputStream
    ) {
        final MediaType mediaType = MediaType.parseMediaType(mimeType);
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        return sendAttachment(attachmentFilename, mediaType, inputStream);
    }

    public static ResponseEntity<InputStreamResource> sendInline(
        String inlineFilename,
        String mimeType,
        InputStream inputStream
    ) {
        final MediaType mediaType = MediaType.parseMediaType(mimeType);
        return sendInline(inlineFilename, mediaType, inputStream);
    }

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        String mimeType,
        InputStream inputStream
    ) {
        final MediaType mediaType = MediaType.parseMediaType(mimeType);
        return sendAttachment(attachmentFilename, mediaType, inputStream);
    }

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        MediaType mediaType,
        File file
    ) {
        try {
            InputStream inputStream = Files.newInputStream(file.toPath());
            return sendAttachment(attachmentFilename, mediaType, inputStream);
        } catch (IOException exception) {
            return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(null);
        }
    }

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        MediaType mediaType,
        ByteArrayOutputStream outputStream
    ) {
        ByteArrayInputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        return sendAttachment(attachmentFilename, mediaType, inputStream);
    }

    public static ResponseEntity<InputStreamResource> sendInline(
        String attachmentFilename,
        MediaType mediaType,
        InputStream inputStream
    ) {
        try {
            InputStreamResource resource = new InputStreamResource(inputStream);
            String filename = encoding(attachmentFilename);
            return ResponseEntity
                .ok()
                .contentType(mediaType)
                .header(HEADER_CONTENT_DISPOSITION, HEADER_INLINE + filename)
                .contentLength(inputStream.available())
                .body(resource);
        } catch (IOException exception) {
            return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(null);
        }
    }

    public static ResponseEntity<InputStreamResource> sendAttachment(
        String attachmentFilename,
        MediaType mediaType,
        InputStream inputStream
    ) {
        try {
            InputStreamResource resource = new InputStreamResource(inputStream);
            String filename = encoding(attachmentFilename);
            return ResponseEntity
                .ok()
                .contentType(mediaType)
                .header(HEADER_CONTENT_DISPOSITION, HEADER_ATTACHMENT + filename)
                .contentLength(inputStream.available())
                .body(resource);
        } catch (IOException exception) {
            return ResponseEntity
                .status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(null);
        }
    }

    /**
     * 处理字符串为utf-8编码格式。
     *
     * @param value 待处理字符串
     * @return 处理结果
     */
    private static String encoding(String value) throws UnsupportedEncodingException {
        return URLEncoder.encode(value, StandardCharsets.UTF_8);
    }
}
